
#include <BReadWrite>
#include <BCursor>
#include <BPainter>
#include <BMouseEvent>
#include <BStyle>
#include <BFile>
#include <BStyleDocument>

#include "StyleFormat.h"

StyleFormat::StyleFormat()
{
	_textEdit = 0;
	_dirtyLines = true;
}
StyleFormat::~StyleFormat()
{

}

void StyleFormat::styled(const BStyle* style)
{	
	_nameFont = new BFont(*style->font());
	_nameFont->setMonospace(true);

	_signFont = new BFont(*style->font());
	_signFont->setMonospace(true);

	_noteFont = new BFont(*style->font());
	_noteFont->setMonospace(true);

}
void StyleFormat::changed(const BString& text)
{
	_nodeMap.reset();
	BString str;
	for (auto it = text.begin(); it.valid(); ++it)
	{
		if (it == '{')
		{
			StyleFormat::Node& splitNode = this->insert(it.count(), it.count() + 1);
			splitNode.color.set(0, 0, 120);

			StyleFormat::Node& node = this->insert(it.count() - str.count(), it.count());
			node.font = _nameFont;
			node.color.set(50, 100, 150);
			str.clear();
			continue;
		}
		if (it == '}')
		{
			StyleFormat::Node& splitNode = this->insert(it.count(), it.count() + 1);
			splitNode.color.set(0, 0, 120);
			continue;
		}
		if (it == ':')
		{
			StyleFormat::Node& splitNode = this->insert(it.count(), it.count() + 1);
			splitNode.color.set(0, 0, 120);

			StyleFormat::Node& node = this->insert(it.count() - str.count(), it.count());
			node.font = _signFont;
			str.trimmed();
			if (str.beginWith('*'))
				node.color.set(100, 150, 50);
			else
				node.color.set(0, 0, 0);
			str.clear();
			continue;
		}
		if (it == ';')
		{
			StyleFormat::Node& semiNode = this->insert(it.count(), it.count() + 1);
			semiNode.color.set(0, 0, 120);

			StyleFormat::Node& node = this->insert(it.count() - str.count(), it.count());
			node.font = _signFont;
			node.color.set(120, 80, 50);
			str.clear();
			continue;
		}
		if (it == '/' && (it + 1) == '*')
		{
			auto end = text.find("*/", it);
			if (end.valid())
				end += 2;
			StyleFormat::Node& node = this->insert(it.count(), end.count());
			node.font = _noteFont;
			node.color.set(50, 150, 100);
			str.clear();
			it = end;
			continue;
		}
		if (it == '/' && (it + 1) == '/')
		{
			auto end = text.find('\n', it);
			if (end.valid())
				end += 1;
			StyleFormat::Node& node = this->insert(it.count(), end.count());
			node.font = _noteFont;
			node.color.set(50, 150, 100);
			str.clear();
			it = end;
			continue;
		}
		str.append(*it);
	}
}

void StyleFormat::slotAssetChanged(BObject* object, const BValue& value)
{
	BTextEdit* textEdit = this->asset();
	if (_textEdit != textEdit)
	{
		if (_textEdit)
		{
			disconnect(_textEdit);
		}
		_textEdit = textEdit;
		if (_textEdit)
		{
			connect(_textEdit, Signal_Freshed, &StyleFormat::slotEditFreshed);
			connect(_textEdit, Signal_Framed, &StyleFormat::slotEditFramed);
		}
	}
}

void StyleFormat::slotEditFreshed(BObject* object, const BValue& value)
{
	if (_dirtyLines)
	{
		BString text = _textEdit->lineCount();
		BSize textSize = _textEdit->realFont()->textSize(text);
		if (_textEdit->perch(Part_Left) < textSize.width())
			_textEdit->setPerch(Part_Left, textSize.width());
	}
}
void StyleFormat::slotEditFramed(BObject* object, const BValue& value)
{
	BPainter painter(_textEdit);
	for (auto it = _nodeMap.begin(); it != _nodeMap.end(); it++)
	{
		const BRect& cell = _textEdit->codeRect(it.key());
		painter.setColor(it->color);
		painter.drawLine(cell.leftTop(), cell.leftBottom());
		painter.fillCircle(cell.leftBottom(), 5);
	}

	BRect leftRect = _textEdit->rect(Part_Left);
	BIntArray& visualLines = _textEdit->query("visual-lines");
	painter.setClip(leftRect + BSize(1, 1));
	painter.setColor(Color_Text);
	for (int i = 0; i < visualLines.size(); i++)
	{
		int line = visualLines[i];
		BRect lrect = _textEdit->lineRect(line);
		lrect.left() = leftRect.left();
		lrect.right() = leftRect.right();
		painter.drawText(lrect, line);
	}

}
